import scala.swing.Component
import java.awt.Color
import java.awt.Dimension
import scala.Predef._
import scala.collection.mutable._
import dataflowVariety.CustomAttribute
import dataflowVariety.AttributeFactory
import scala.swing.event.ButtonClicked
import scala.swing.event.ActionEvent

package layoutVariety
{ 
	class Widget (ref:Int) 
	{
		protected var jc:Component = null
		
		def getWidget = jc
		
		private val ID = ref
		
		//preparing map for setters functions
		protected var namesToFuncs = HashMap[String,AnyRef=>Unit]()
		
		namesToFuncs("enabled") = setEnabled
		namesToFuncs("bgcolor") = setBackground
		namesToFuncs("fgcolor") = setForeground
		namesToFuncs("width") = setWidth
		namesToFuncs("height") = setHeight
		
		/** handlers API **/
		
		// map reaction types to the addReaction methods
		type Handler = ()=>Unit
		protected val reactionsMap = HashMap[String, (Component, Handler)=>Unit]()  
		reactionsMap("onClick") = (c: Component, h: Handler) => c.reactions+={case ButtonClicked(_) => h();}
        reactionsMap("onChange") = (c: Component, h: Handler) => c.reactions+={case ActionEvent(_) => h();}
		
        // adds a handler to a specific UI component
        def addHandler(event: String, handler: Handler)
		{
          reactionsMap(event)(jc,handler);
		}


		/*****************/
		
		// we hold the custom attributes as a map between the custom attribute and the 
		// real attribute it affects (using a hashmap to map the custom 
		// attribute values and the real attribute values). 
		
		private var customAttrs : HashMap[String,List[String]] = HashMap();
		private var realAttrs : HashMap[String,String] = HashMap();
			
		def isEnabled = jc.enabled
		
		def setEnabled(ref:AnyRef)
		{
			var enb = ref.asInstanceOf[Boolean]
			
			jc.enabled = enb
		}
		
		def setBackground(ref:AnyRef)
		{
			var bg = ref.asInstanceOf[Int]
			var c = new Color(bg%(2^8),(bg/2^8)%(2^8),(bg/(2^16))%(2^8)) 
	
			jc.background = c
		}
		
		def getBackground = jc.background
		
		def setForeground(ref:AnyRef)
		{
			var fg = ref.asInstanceOf[Int]
			var c = new Color(fg%(2^8),(fg/2^8)%(2^8),(fg/(2^16))%(2^8)) 
		
			jc.foreground = c
		}
		
		def getForeground = jc.foreground
		
		def setWidth(ref:AnyRef)
		{
			var w = ref.asInstanceOf[Int]
		    setSize((w,getSize.height)) 
		}
		
		def setHeight(ref:AnyRef)
		{
			var h = ref.asInstanceOf[Int]
		    setSize((getSize.width,h)) 
		}
		
		def setSize(s:(Int,Int))
		{
			var d  = new Dimension(s._1,s._2)
			jc.maximumSize = d
			jc.minimumSize = d
			jc.preferredSize = d
		}
		
		def getSize = jc.size
			
		def setCustomAttribute(realName:String,att:CustomAttribute, isBidi : Boolean)
		{		  
		  // check if the attribute already exists:
		  if(customAttrs.isDefinedAt(att.getName))
		  {
			  // add the value to the map 
			  var l = customAttrs(att.getName)
			  l  :+= realName;			  
		  }
		  else
		  {		        
			  // add the value to the map 
			  customAttrs(att.getName) = List(realName);
		  }		  
		    
		  // register the widget as an observer
		  att.regiserObserver(this)
		  
		  //in order to allow bidirectional assignment
		  if (isBidi)
		  {
		    realAttrs(realName) = att.getName
		    
		    def f() 
		    {
		      
		      AttributeFactory.changeCustomAttr(att.getName,getAttByName(realName))
		    }
		    
		    addHandler("onChange", f)
		  }
		  //realAttrs(pair._1) = (att.getName,pair._2)
		
		}
			
		def update(attName:String,currentVal:String)
		{
		 	for(a <- customAttrs(attName))
		  	{			  	
				// the real attribute name is the left part of the tuple
				val realAttrName = a
						
				setAttByName(realAttrName,currentVal.asInstanceOf[AnyRef])
		  	}
	
		}
		
		def setAttByName(name:String,value:AnyRef)
		{
			namesToFuncs(name)(value)
		}
		
		def getAttByName(name:String):String = 
		{
			var value:String = null
			if (name == "enabled")
			{
			  var v = isEnabled
			  if (v) value = 1.toString()
			  else value = 0.toString()
			}
			
			if (name == "checked")
			{
			  var v = this.asInstanceOf[Toggle].isChecked
			  if (v) value = 1.toString()
			  else value = 0.toString()
			}
			
			if (name == "width")
			{
			  var v = getSize
			  value = v.getWidth().toString()
			}
			
			if (name == "height")
			{
			  var v = getSize
			  value = v.getHeight().toString()
			}
			
			if (name == "text")
			{
			  value = this.asInstanceOf[Label].getText
			}
			
			if (name == "minvalue")
			{
			  value = this.asInstanceOf[Slider].getMin.toString()
			}
			
			if (name == "maxvalue")
			{
			  value = this.asInstanceOf[Slider].getMax.toString()
			}
			
			if (name == "value")
			{
			  value = this.asInstanceOf[Slider].getVal.toString()
			}
			
			value
		}
	}
}